import socket
import logging
from contextlib import contextmanager
from apscheduler.schedulers.base import BaseScheduler
from apscheduler.schedulers.background import BackgroundScheduler

from localsvc.proxy import nginxproxy

_logger = logging.getLogger(__name__)

def _get_random_port():
    '''Get random not used port
    '''
    with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
        s.bind(('', 0))
        addr = s.getsockname()
        return addr[1]

class ApplicationContainer:
    '''Bean container
    '''

    __scheduler: BaseScheduler
    __nginx_proxy: nginxproxy.NginxProxy

    def __init__(self) -> None:
        self.__scheduler = None
        self.__nginx_proxy = None

    def get_scheduler(self) -> BaseScheduler:
        '''Get bean Scheduler
        '''
        if self.__scheduler is None:
            self.__scheduler = BackgroundScheduler()
            self.__scheduler.start()
        return self.__scheduler

    def get_nginx_proxy(self):
        '''Get bean NginxProxy
        '''
        if self.__nginx_proxy is None:
            ngx_port = _get_random_port()
            _logger.info('Nginx will listen on port %d', ngx_port)
            self.__nginx_proxy = nginxproxy.NginxProxy(ngx_port)
        return self.__nginx_proxy

    def after_setup(self):
        '''Do something after all setting ups
        '''
        if self.__nginx_proxy:
            self.__nginx_proxy.start()

    def dispose(self):
        '''Release resources
        '''
        if self.__nginx_proxy is not None:
            self.__nginx_proxy.stop()


@contextmanager
def open_container():
    c = ApplicationContainer()
    try:
        yield c
    finally:
        c.dispose()
